﻿using System;
using System.Collections.Generic;
using AutoCorrelatorGUI.Model;
using AutoCorrelatorGUI.Properties;
using AutoCorrelatorGUI.Utility;
using AutoCorrelatorGUI.ViewModel.Messages;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Win32;

using System.Collections;
using Common.Utility;
using Common.ViewModel;

namespace AutoCorrelatorGUI.ViewModel
{
   /// <summary>
   /// This class contains properties that a View can data bind to.
   /// <para>
   /// See http://www.galasoft.ch/mvvm
   /// </para>
   /// </summary>
   public class OptionsViewModel : ViewModelBase
   {
      private IDataService _DataService = null;

      /// <summary>
      /// Initializes a new instance of the MvvmViewModel1 class.
      /// </summary>
      public OptionsViewModel(IDataService dataService)
      {
         _DataService = dataService;

         Messenger.Default.Register<FullRefreshMessage>(this, OnFullRefresh);

         //Request any existing data
         Messenger.Default.Send(new RequestDataMessage(OnFullRefresh));
      }

      /// <summary>
      /// The <see cref="CompareWell" /> property's name.
      /// </summary>
      public const string CompareWellPropertyName = "CompareWell";

      public static WellVM CompareWellSetting = null;

      /// <summary>
      /// Sets and gets the CompareWell property.
      /// Changes to that property's value raise the PropertyChanged event. 
      /// </summary>
      public WellVM CompareWell
      {
         get
         {
            return CompareWellSetting;
         }

         set
         {
            if (CompareWellSetting == value)
            {
               return;
            }

            CompareWellSetting = value;

            RaisePropertyChanged(CompareWellPropertyName);

            if (CompareWellSetting != null)
            {
               Settings.Default.ComparisonWellStr = CompareWellSetting.Title;

               //Update the data service
               _DataService.SetCompareWell(Settings.Default.ComparisonWellStr);
            }
         }
      }

      public IEnumerable<KeyValuePair<Enum, string>> NormalizationOptionList
      {
         get
         {
            List<KeyValuePair<Enum, string>> normEnum = (List<KeyValuePair<Enum, string>>)EnumHelper.GetAllValuesAndDescriptions<NormalizationTypes>();

            if (!Settings.Default.PerformAutoCorrelation)
            {
               for (int i = 0; i < normEnum.Count; i++)
               {
                  if ((NormalizationTypes)normEnum[i].Key == NormalizationTypes.VarianceFunction)
                  {
                     normEnum.RemoveAt(i);
                     break;
                  }
               }
            }

            return normEnum;
         }
      }

      /// <summary>
      /// The <see cref="NormalizationChoice" /> property's name.
      /// </summary>
      public const string NormalizationChoicePropertyName = "NormalizationChoice";

      /// <summary>
      /// Sets and gets the NormalizationChoice property.
      /// Changes to that property's value raise the PropertyChanged event. 
      /// </summary>
      public NormalizationTypes NormalizationChoice
      {
         get
         {
            return Settings.Default.NormalizationMethod;
         }

         set
         {
            if (Settings.Default.NormalizationMethod == value)
            {
               return;
            }

            Properties.Settings.Default.NormalizationMethod = value;
            RaisePropertyChanged(NormalizationChoicePropertyName);

            //Update the data service
            _DataService.SetNormalization(Settings.Default.NormalizationMethod);
         }
      }

      /// <summary>
      /// The <see cref="CalcFirstDerivative" /> property's name.
      /// </summary>
      public const string CalcFirstDerivativePropertyName = "CalcFirstDerivative";

      /// <summary>
      /// Sets and gets the CalcFirstDerivative property.
      /// Changes to that property's value raise the PropertyChanged event. 
      /// </summary>
      public bool CalcFirstDerivative
      {
         get
         {
            return Settings.Default.CalcFirstDerivative;
         }

         set
         {
            if (Settings.Default.CalcFirstDerivative == value)
            {
               return;
            }

            Settings.Default.CalcFirstDerivative = value;
            RaisePropertyChanged(CalcFirstDerivativePropertyName);

            //Update the data service
            _DataService.SetCalcDerivative(Settings.Default.CalcFirstDerivative);
         }
      }

      /// <summary>
      /// The <see cref="IntervalTimeMS" /> property's name.
      /// </summary>
      public const string IntervalTimeMSPropertyName = "IntervalTimeMS";

      /// <summary>
      /// Sets and gets the IntervalTimeMS property.
      /// Changes to that property's value raise the PropertyChanged event. 
      /// </summary>
      public double IntervalTimeMS
      {
         get
         {
            return Properties.Settings.Default.IntervalTimeMS;
         }

         set
         {
            if (Properties.Settings.Default.IntervalTimeMS == value)
            {
               return;
            }

            Properties.Settings.Default.IntervalTimeMS = value;
            RaisePropertyChanged(IntervalTimeMSPropertyName);

            //Update the data service
            _DataService.SetIntervalTime(Settings.Default.IntervalTimeMS);
         }
      }

      public IEnumerable<KeyValuePair<Enum, string>> MotherWaveletOptionList
      {
         get
         {
            return EnumHelper.GetAllValuesAndDescriptions<MotherWaveletTypes>();
         }
      }

      /// <summary>
      /// The <see cref="NormalizationChoice" /> property's name.
      /// </summary>
      public const string MotherWaveletChoicePropertyName = "MotherWaveletChoice";

      /// <summary>
      /// Sets and gets the NormalizationChoice property.
      /// Changes to that property's value raise the PropertyChanged event. 
      /// </summary>
      public MotherWaveletTypes MotherWaveletChoice
      {
         get
         {
            return Settings.Default.MotherWavelet;
         }

         set
         {
            if (Settings.Default.MotherWavelet == value)
            {
               return;
            }

            Properties.Settings.Default.MotherWavelet = value;
            RaisePropertyChanged(MotherWaveletChoicePropertyName);

            //Update the data service
            _DataService.SetMotherWavelet(Settings.Default.MotherWavelet);
         }
      }

      private MultiSelectBindingList<WellVM> _InternalWellData = null;

      public MultiSelectBindingList<WellVM> InternalWellData
      {
         get { return _InternalWellData; }
         set
         {
            _InternalWellData = value;
            RaisePropertyChanged("InternalWellData");
         }
      }

      private void OnFullRefresh(FullRefreshMessage message)
      {
         InternalWellData = message.DataView.SourceCollection as MultiSelectBindingList<WellVM>;

         RaisePropertyChanged("NormalizationOptionList");

         if (!Settings.Default.PerformAutoCorrelation && NormalizationChoice == NormalizationTypes.VarianceFunction)
         {
            NormalizationChoice = NormalizationTypes.None;
         }

         //Now update the comparison item if necessary
         if (_InternalWellData != null && _InternalWellData.Count > 0)
         {
            CompareWell = null;

            foreach (WellVM well in _InternalWellData)
            {
               if (well.Title == Properties.Settings.Default.ComparisonWellStr)
               {
                  CompareWell = well;
                  break;
               }
            }

            //Pick the first if it wasnt found
            if (CompareWell == null)
               CompareWell = _InternalWellData[0] as WellVM;
         }
      }
   }
}
